package com.fjec.common.filter;

import com.google.common.base.Strings;
import com.vdurmont.emoji.EmojiParser;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.owasp.validator.html.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

@Slf4j
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {

    private List<String> whiteList = new ArrayList<>();
    /**
     * AntiSamy使用的策略文件
     */
    private static Policy policy = null;

//    static {
//        try {
//            InputStream is = XssHttpServletRequestWrapper.class
//                    .getClassLoader()
//                    .getResourceAsStream("antisamy-ebay.xml");
//            policy = Policy.getInstance(is);
//        } catch (PolicyException e) {
//            log.error(e.getMessage(), e);
//        }
//    }

    public XssHttpServletRequestWrapper(HttpServletRequest request) {
        super(request);
        // 设置白名单
        setWhiteList();
        // 初始化清洗
        try {
            InputStream is = this.getClass().getResourceAsStream("/antisamy/antisamy-myspace.xml");
            policy = Policy.getInstance(is);
        } catch (PolicyException e) {
            log.error(e.getMessage(), e);
        }
    }

    private void setWhiteList() {
        whiteList.add("articleContent");
    }

    /**
     * Header为空直接返回，不然进行XSS清洗
     *
     * @param name
     * @return
     */
    @Override
    public String getHeader(String name) {
        String value = super.getHeader(name);
        if (Strings.isNullOrEmpty(value)) {
            return value;
        } else {
            String newValue = cleanXSS(value);
            return newValue;
        }

    }

    /**
     * Parameter为空直接返回，不然进行XSS清洗
     *
     * @param name
     * @return
     */
    @Override
    public String getParameter(String name) {
        String value = super.getParameter(name);
        if (Strings.isNullOrEmpty(value)) {
            return value;
        } else {
            value = cleanXSS(value);
            return value;
        }
    }

    /**
     * 对用户输入的参数值进行XSS清洗
     *
     * @param name
     * @return
     */
    @Override
    public String[] getParameterValues(String name) {
        String[] values = super.getParameterValues(name);
        if (values != null) {
            int length = values.length;
            String[] escapseValues = new String[length];
            for (int i = 0; i < length; i++) {
                escapseValues[i] = cleanXSS(values[i]);
            }
            return escapseValues;
        }
        return super.getParameterValues(name);
    }


    /**
     * @return
     */
    public Map<String, String[]> getParameterMap() {
        Map<String, String[]> request_map = super.getParameterMap();
        Iterator iterator = request_map.entrySet().iterator();
//        System.out.println("request_map" + request_map.size());
        while (iterator.hasNext()) {
            Map.Entry me = (Map.Entry) iterator.next();
            if (!whiteList.contains(me.getKey())) {
                if (log.isDebugEnabled()) {
                    log.debug(me.getKey() + ":");
                }
                String[] values = (String[]) me.getValue();
                for (int i = 0; i < values.length; i++) {
                    if (log.isDebugEnabled()) {
                        log.debug(values[i]);
                    }
                    values[i] = cleanXSS(values[i]);
                }
            }
        }
        return request_map;
    }

    /**
     * AntiSamy清洗数据
     *
     * @param taintedHTML
     * @return
     */
    private String cleanXSS(String taintedHTML) {
        String result = EmojiParser.replaceAllEmojis(taintedHTML, "□");
        try {
            AntiSamy antiSamy = new AntiSamy();
            CleanResults cr = antiSamy.scan(result, policy);
            result = cr.getCleanHTML();
            if (!StringUtils.isEmpty(result) && result.contains("&quot;")) {
                result = result.replace("&quot;", "\"");
            }
            if (!StringUtils.isEmpty(result) && result.contains("&amp;")) {
                result = result.replace("&amp;", "&");
            }
        } catch (ScanException e) {
            log.error(e.getMessage(), e);
        } catch (PolicyException e) {
            log.error(e.getMessage(), e);
        }
        return result;
    }

}
